package com.tsfyun.scm.service.impl.order;

import cn.hutool.core.collection.CollUtil;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.tsfyun.common.base.enums.RateTypeEnum;
import com.tsfyun.common.base.exception.ServiceException;
import com.tsfyun.common.base.extension.ServiceImpl;
import com.tsfyun.common.base.util.LocalDateTimeUtils;
import com.tsfyun.common.base.util.TsfPreconditions;
import com.tsfyun.scm.base.DataCalling;
import com.tsfyun.scm.dto.order.ImpOrderPaySituationQTO;
import com.tsfyun.scm.entity.customer.SupplierBank;
import com.tsfyun.scm.entity.order.ImpOrder;
import com.tsfyun.scm.mapper.order.ImpOrderMapper;
import com.tsfyun.scm.service.customer.IImpClauseService;
import com.tsfyun.scm.service.customer.ISupplierBankService;
import com.tsfyun.scm.service.order.IImpOrderPaymentService;
import com.tsfyun.scm.vo.customer.ImpClauseOrderVO;
import com.tsfyun.scm.vo.order.ApplyPaymentPlusVO;
import com.tsfyun.scm.vo.order.ApplyPaymentVO;
import com.tsfyun.scm.vo.order.ImpOrderPaySituationVO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

@Service
public class ImpOrderPaymentServiceImpl extends ServiceImpl<ImpOrder> implements IImpOrderPaymentService {

    @Autowired
    private ImpOrderMapper impOrderMapper;
    @Autowired
    private ISupplierBankService supplierBankService;
    @Autowired
    private IImpClauseService impClauseService;

    @Override
    public PageInfo<ImpOrderPaySituationVO> list(ImpOrderPaySituationQTO qto) {
        PageHelper.startPage(qto.getPage(),qto.getLimit());
        Map<String,Object> params = beanMapper.map(qto,Map.class);
        List<ImpOrderPaySituationVO> list = impOrderMapper.paySituationList(params);
        return new PageInfo<>(list);
    }

    @Override
    public ApplyPaymentPlusVO initApply(List<Long> ids){
        TsfPreconditions.checkArgument(CollUtil.isNotEmpty(ids),new ServiceException("请至少选择一个订单申请付汇"));
        List<ImpOrderPaySituationVO> list = paySituationByIds(ids);
        TsfPreconditions.checkArgument(CollUtil.isNotEmpty(list),new ServiceException("请至少选择一个订单申请付汇"));
        ApplyPaymentVO payment = new ApplyPaymentVO();
        payment.setAccountValue(BigDecimal.ZERO);
        Long customerId = null;
        String currencyId = null;
        Long supplierId = null;
        String supplierName = null;
        for(int i=0;i<list.size();i++){
            ImpOrderPaySituationVO iops = list.get(i);
            if(Objects.nonNull(customerId)&&!Objects.equals(iops.getCustomerId(),customerId)){
                throw new ServiceException(String.format("订单【%s】所选客户不一致，无法合并付汇",iops.getDocNo()));
            }
            if(Objects.nonNull(currencyId)&&!Objects.equals(iops.getCurrencyId(),currencyId)){
                throw new ServiceException(String.format("订单【%s】所选币制不一致，无法合并付汇",iops.getDocNo()));
            }
            BigDecimal allowApplyVal = iops.getTotalPrice().subtract(iops.getApplyPayVal()).setScale(2,BigDecimal.ROUND_HALF_UP);
            if(allowApplyVal.compareTo(BigDecimal.ZERO)==-1){
                throw new ServiceException(String.format("订单【%s】可申请金额不足",iops.getDocNo()));
            }
            customerId = iops.getCustomerId();
            currencyId = iops.getCurrencyId();
            //订单供应商
            if(Objects.isNull(supplierId)){
                supplierId = iops.getSupplierId();
                supplierName = iops.getSupplierName();
            }
            payment.setAccountValue(payment.getAccountValue().add(allowApplyVal).setScale(2,BigDecimal.ROUND_HALF_UP));
        }

        //合并付汇验证汇率时间是否一致
        List<ImpClauseOrderVO> impClauseOrderVOS = impClauseService.checkOrderIdsGoodsRateTime(ids,Boolean.TRUE);

        //赋值主单数据
        payment.setCustomerId(list.get(0).getCustomerId());
        payment.setCustomerName(list.get(0).getCustomerName());
        payment.setCurrencyId(list.get(0).getCurrencyId());
        payment.setCurrencyName(list.get(0).getCurrencyName());
        //获取当日中行九点半汇率
        payment.setAccountDate(LocalDateTimeUtils.convertLocalDateRemoveSecond());
        String goodsRateTime = impClauseOrderVOS.get(0).getGoodsRateTime();
        payment.setGoodsRateTime(goodsRateTime);
        String rateTime = LocalDateTimeUtils.convertLocalAddHourMinuteStr(payment.getAccountDate(),goodsRateTime);
        RateTypeEnum rateType = RateTypeEnum.PAY_BANK_CHINA_SELL;
        BigDecimal chinaRate = DataCalling.getInstance().obtainBankChinaRate(payment.getCurrencyId(), rateType.getCode(),rateTime);
        TsfPreconditions.checkArgument(Objects.nonNull(chinaRate),new ServiceException(String.format("%s 外汇牌价卖出价暂未公布，请稍后重试",goodsRateTime)));
        payment.setExchangeRate(chinaRate);
        //收款人
        if(Objects.nonNull(supplierId)){
            payment.setPayeeId(supplierId);
            payment.setPayeeName(supplierName);
            //获取供应商默认银行信息
            SupplierBank supplierBank = supplierBankService.defSupplierBank(supplierId);
            if(Objects.nonNull(supplierBank)){
                payment.setPayeeBankId(supplierBank.getId());
                payment.setPayeeBankName(supplierBank.getName());
                payment.setPayeeBankAccountNo(supplierBank.getAccount());
                payment.setSwiftCode(supplierBank.getSwiftCode());
                payment.setIbankCode(supplierBank.getCode());
                payment.setPayeeBankAddress(supplierBank.getAddress());
            }
        }
        payment.setAccountValueCny(payment.getAccountValue().multiply(payment.getExchangeRate()).setScale(2,BigDecimal.ROUND_HALF_UP));
        // 保证手续费挂入第一个订单
        list.stream().sorted(Comparator.comparing(ImpOrderPaySituationVO::getId)).collect(Collectors.toList());
        return new ApplyPaymentPlusVO(payment,list);
    }

    @Override
    public ApplyPaymentPlusVO clientInitApply(List<Long> ids) {
        return initApply(ids);
    }

    @Override
    public List<ImpOrderPaySituationVO> paySituationByIds(List<Long> orderIds) {
        Map<String,Object> params = new LinkedHashMap<String,Object>(){{
            put("ids",orderIds);
        }};
        return impOrderMapper.paySituationList(params);
    }


}
